package dp.mobile.level;

import java.util.ArrayList;
import org.w3c.dom.Node;

import dp.mobile.entity.generator.GeneratorFactory;
import dp.mobile.entity.tower.TowerFactory;
import dp.mobile.glwrapper.GameRenderer;

import android.util.Log;


public class Level {
	private static final String TAG = "Level";
	
	protected Level() {
		//Initialize
		mName		= "";
		mIndex		= 0;
		mStartX		= new ArrayList<Integer>();
		mStartY		= new ArrayList<Integer>();
		mFinishX	= new ArrayList<Integer>();
		mFinishY	= new ArrayList<Integer>();
		mStartGold	= 0;
		mGoldGoal	= -1;
		mTimeGoal	= -1;
		mStartComponents = new int[] {0, 0, 0};
		GeneratorFactory.instance().getBaseGenerator();
		mTowerGoal	= new int[TowerFactory.instance().getTowerNumber()];
		for (int i = 0; i < mTowerGoal.length; i++) mTowerGoal[i] = -1;

		//Empty
		mMap		= null;
		mGenerator	= null;
		mPathX		= new ArrayList<int[]>();
		mPathY		= new ArrayList<int[]>();
		mTowers		= null;
		mWaves		= new ArrayList<Wave>();
		mDialogs	= new ArrayList<Dialog>();
		mCutScenes	= new ArrayList<CutScene>();
	}
	
	public Level(Node root, boolean isOnlyName){
		mName = "";
		if(!isOnlyName)
			return;
		else{
			int childCount = root.getChildNodes().getLength();
			for (int i = 0; i < childCount; ++i) {
				Node elem = root.getChildNodes().item(i);
				if (elem.getNodeType() == Node.TEXT_NODE) continue;
				
				String tag 		= elem.getNodeName();
				String value 	= elem.getFirstChild().getNodeValue();
				
				if (tag.equals("name")) 	mName 		= value;
			}
		}
	}
	
	public Level(Node root) {
		this();
		// Temp data
		String set 	= null;
		String map 	= null;
		String node = "";
		
		int childCount = root.getChildNodes().getLength();
		for (int i = 0; i < childCount; ++i) {
			Node elem = root.getChildNodes().item(i);
			if (elem.getNodeType() == Node.TEXT_NODE) continue;
			
			String tag 		= elem.getNodeName();
			String value 	= elem.getFirstChild().getNodeValue();
			
			if (tag.equals("index")) 		mIndex 		= Integer.parseInt(value);
			else if (tag.equals("gold")) 	mStartGold 	= Integer.parseInt(value);
			else if (tag.equals("life")) 	mStartLife 	= Integer.parseInt(value);
			else if (tag.equals("name")) 	mName 		= value;
			else if (tag.equals("tileset")) set			= value;
			else if (tag.equals("map")) 	map 		= value;
			else if (tag.equals("nodes")) 	node 		= value;
			else if (tag.equals("component")) {
				if (elem.getAttributes().getNamedItem("type") != null) {
					int type = Integer.parseInt(elem.getAttributes().getNamedItem("type").getNodeValue());
					mStartComponents[type] = Integer.parseInt(value);
				}
			}
			else if (tag.equals("start")) {
				String[] point 	= value.split(",");
				mStartX.add(Integer.parseInt(point[0]));
				mStartY.add(Integer.parseInt(point[1]));
			}
			else if (tag.equals("towers")) {
				String[] towers	= value.split(";");
				mTowers			= new int[towers.length];
				for (int j = 0; j < mTowers.length; j++) mTowers[j] = Integer.parseInt(towers[j]);
			}
			else if (tag.equals("generators")) {
				String[] generators	= value.split(";");
				mGenerator			= new int[generators.length];
				for (int j = 0; j < mGenerator.length; j++) mGenerator[j] = Integer.parseInt(generators[j]);
			}
			else if (tag.equals("path")) {
				String points[] = value.split(";");
            	int[] tempPathX = new int[points.length];
            	int[] tempPathY = new int[points.length];
            	
            	for(int j=0; j < points.length; ++j){
            		String point[] = points[j].split(",");
            		tempPathX[j] = Integer.parseInt(point[0]);
            		tempPathY[j] = Integer.parseInt(point[1]);
            	}

				//Get finish position
				final int tempFinishX = tempPathX[tempPathX.length - 1];
				final int tempFinishY = tempPathY[tempPathY.length - 1];
				
				mPathX.add(tempPathX);
				mPathY.add(tempPathY);
				
				mFinishX.add(tempFinishX);
				mFinishY.add(tempFinishY);
			}
			else if (tag.equals("waves")) {
				int grandChildCount = elem.getChildNodes().getLength();
				for (int j = 0; j < grandChildCount; j++) {
					Node waveChild = elem.getChildNodes().item(j);
					if (waveChild.getNodeType() == Node.TEXT_NODE) continue;
            		mWaves.add(new Wave(waveChild));
				}
			}
			else if (tag.equals("story")) {
				//For each child
				int grandChildCount = elem.getChildNodes().getLength();
            	for (int j = 0; j < grandChildCount; j++) {
            		Node dialogChild = elem.getChildNodes().item(j);
            		if (dialogChild.getNodeType() == Node.TEXT_NODE) continue;
					//If dialogs, add
					if (dialogChild.getNodeName().equals("dialogs"))
						mDialogs.add(new Dialog(dialogChild));
				}
			} else if (tag.equals("goal")) {
				//For each children
				int storyChildrenCount = elem.getChildNodes().getLength();
				for (int j = 0; j < storyChildrenCount; j++) {
					//Get tag and value
					Node storyElem = elem.getChildNodes().item(j);
					if (storyElem.getNodeType() == Node.TEXT_NODE) continue;
					
					tag 	= storyElem.getNodeName();
					value 	= storyElem.getFirstChild().getNodeValue();

					//Get value
					if (tag.equals("gold"))			mGoldGoal = Integer.parseInt(value);
					else if (tag.equals("time"))	mTimeGoal = (long) (Float.parseFloat(value) * 1000);
					else if (tag.equals("tower")) {
						//Reset
						for (int k = 0; k < mTowerGoal.length; k++) mTowerGoal[k] = -1;

						//Split
						String[] TowerGoals = value.split(";");
						for (int k = 0; k < TowerGoals.length; k++) {
							//Split again
							String[] TowerGoal = TowerGoals[k].split(":");

							//Read
							int Index	= Integer.parseInt(TowerGoal[0]);
							int Goal	= Integer.parseInt(TowerGoal[1]);

							//Check index
							if (Index >= 1 && Index < mTowerGoal.length) mTowerGoal[Index] = Goal;
						}
					}
				}
			}
		}
		
		//Create map
        if (set != null && map != null) mMap = new Map(map, set, node);
	}
	
	//Accessors
	public Map getMap()						{	return mMap;           	}
	public int getGold()					{	return mStartGold;     	}
	public int[] getComponents()			{	return mStartComponents;}
    public int getLife()					{	return mStartLife;     	}
	public int getStartX(int p)				{	return mStartX.get(p);  }
	public int getStartY(int p)				{	return mStartY.get(p);  }
	public int getFinishX(int p)			{	return mFinishX.get(p); }
	public int getFinishY(int p)			{	return mFinishY.get(p); }
	public int getGoldGoal()				{	return mGoldGoal;		}
	public long getTimeLimit()				{	return mTimeGoal;		}
	public int[] getTowerGoal()				{	return mTowerGoal;		}
    public int getWaveLength()          	{   return mWaves.size();	}
	public int[] getPathX(int p)			{	return mPathX.get(p);   }
	public int[] getPathY(int p)			{	return mPathY.get(p);   }
	public int[] getAvailableGenerators()	{	return mGenerator;		}
	public int[] getAvailableTowers()		{	return mTowers;        	}
	public String getName()					{	return mName;			}
	
	public Wave getWave(int index) {
		//Check index
		if (index < 0)				return null;
		if (index >= mWaves.size())	return null;

		//Return a wave
		return mWaves.get(index);
	}

	public Dialog getDialog(int wave) {
		//Initial
		int i			= 0;
		Dialog Selected = null;

		//While not found
		while (i < mDialogs.size() && Selected == null) {
			//Get wave if wave is the same
			if (mDialogs.get(i).getWave() == wave) Selected = mDialogs.get(i);

			//next
			i++;
		}

		if(Selected != null)
			Selected.loadCharacterImg();

		//Return the selected dialog
		return Selected;
	}
	
	//Data
	protected String	mName;
	protected int		mIndex;
	protected ArrayList<Wave>	mWaves;
	protected ArrayList<Dialog>	mDialogs;
	protected ArrayList<CutScene> mCutScenes;
	protected int[]		mGenerator;
	protected int[]		mTowers;
	protected int[]		mStartComponents;
	protected int		mStartGold;
    protected int       mStartLife;

	//Goal
	protected long	mTimeGoal;
	protected int	mGoldGoal;
	protected int[]	mTowerGoal;

	//Pathing
	protected ArrayList<Integer> mStartX;
	protected ArrayList<Integer> mStartY;
	protected ArrayList<Integer> mFinishX;
	protected ArrayList<Integer> mFinishY;
	protected ArrayList<int[]> mPathX;	//path
	protected ArrayList<int[]> mPathY;	//path

	//Entities
	protected Map mMap;
}
